package com.activitiTest.test1;

import java.util.List;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;

/**
 * author : 冯孟活 ^_^
 * dates  : 2015年8月29日 下午3:11:24
 * class   : 简单 Activiti 测试
 */
public class ActivitiTest {
	/**
	 *  代码清单中使用 ProcessEngines类加载默认的流程配置文件(activiti.cfg.xml)，再获取各个服务组件的实例。
	 *  RepositoryService主要用于管理流程的资源， RuntimeService主要用于流程运行时的流程管理，TaskService主要用于管理流程任务。
	 *  最后， HistoricProcessInstance会将工作的流程历史记录下来。
	 *  
	 *  		activiti.cfg.xml
	 *  			|--ProcessEngineConfiguration->读取解析->ProcessEngine(内置7大服务)
	 *  																|--RepositoryService-|--TaskService-|--IdentityService-|--FormService-|
	 *  																|--RuntimeService-|--ManagementService-|--HistoryService-|
	 *  
	 *  1、RepositoryService：【知识库服务】
	 *  		Activiti 中每一个不同版本的业务流程的定义都需要使用一些定义文件，部署文件和支持数据 ( 例如 BPMN2.0 XML 文件，表单定义文件，流程定义图像文件等 )，
	 *  		这些文件都存储在 Activiti 内建的 Repository 中。Repository Service 提供了对 repository 的存取服务。
	 *  
	 *  2、RuntimeService：【运行服务】
	 *  		在 Activiti 中，每当一个流程定义被启动一次之后，都会生成一个相应的流程对象实例。
	 *  		Runtime Service 提供了启动流程、查询流程实例、设置获取流程实例变量等功能。此外它还提供了对流程部署，流程定义和流程实例的存取服务。
	 *  
	 *  3、TaskService：【任务服务】
	 *  		在 Activiti 中业务流程定义中的每一个执行节点被称为一个 Task，对流程中的数据存取，状态变更等操作均需要在 Task 中完成。
	 *  		Task Service 提供了对用户 Task 和 Form 相关的操作。它提供了运行时任务查询、领取、完成、删除以及变量设置等功能。
	 *  
	 *  4、IdentityService：【身份服务】
	 *  		Activiti 中内置了用户以及组管理的功能，必须使用这些用户和组的信息才能获取到相应的 Task。
	 *  		Identity Service 提供了对 Activiti 系统中的用户和组的管理功能。
	 *  
	 *  5、ManagementService：【管理服务】
	 *  		Management Service 提供了对 Activiti 流程引擎的管理和维护功能，这些功能不在工作流驱动的应用程序中使用，主要用于 Activiti 系统的日常维护。
	 *  
	 *  6、HistoryService：【历史服务】
	 *  		History Service 用于获取正在运行或已经完成的流程实例的信息，与 Runtime Service 中获取的流程信息不同，
	 *  		历史信息包含已经持久化存储的永久信息，并已经被针对查询优化。
	 *  
	 *  7、FormService：【表单服务】
	 *  		Activiti 中的流程和状态 Task 均可以关联业务相关的数据。通过使用 Form Service 可以存取启动和完成任务所需的表单数据并且根据需要来渲染表单。
	 *  
	 *  理解数据库表的命名：
	 *  	Activiti的表都以ACT_开头，第二部分是表示表的用途的两个字母标识，用途也和服务的API对应。
	 *  		1、act_re_* : 're'表示repository,这个前缀的表包含了流程定义和流程静态资源（图片，规则，等等）；
	 *  		2、act_ru_* : 'ru'表示runtime,这些运行的表，包含流程实例，任务，变量，异步任务，等运行中的数据，
	 *  							Activiti只在流程实例执行过程中保存这些数据，在流程结束时就会删除这些记录，这样
	 *  							运行时表可以一直很小速度很快；
	 *  		3、act_id_* : 'id'表示identity,这些表包含身份信息，比如用户，组等等；
	 *  		4、act_hi_* : 'hi'表示history,这些表包含历史数据，比如历史流程实例，变量，任务等等；
	 *  		5、act_ge_* : 通用数据，用于不同场景下；
	 */
	@Test
	public void processTests(){
	    // 通过加载配置文件得到流程引擎
	    ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").buildProcessEngine();
	    // 通过流程引擎得到对应的服务
	    RepositoryService repositoryService = processEngine.getRepositoryService(); // 获取 知识库服务
	    RuntimeService runtimeService = processEngine.getRuntimeService(); // 获取 运行服务
	    repositoryService.createDeployment().addClasspathResource("Interview.bpmn").deploy(); // 通过 知识库服务来部署流程定义（也就是【部署流程定义】部署.bpmn）
	    String processId = runtimeService.startProcessInstanceByKey("Interview").getId(); // 通过运行服务来启动已经部署的流程（也就是【启动流程实例】）
	 
	    TaskService taskService = processEngine.getTaskService(); // 获取 任务服务
	    //得到笔试的流程
	    System.out.println("\n***************笔试流程开始***************");
	 
	    List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
	    for (Task task : tasks) {
	        System.out.println("人力资源部的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.claim(task.getId(), "张三");
	    }
	 
	    System.out.println("张三的任务数量："+taskService.createTaskQuery().taskAssignee("张三").count());
	    tasks = taskService.createTaskQuery().taskAssignee("张三").list();
	    for (Task task : tasks) {
	        System.out.println("张三的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.complete(task.getId());
	    }
	 
	    System.out.println("张三的任务数量："+taskService.createTaskQuery().taskAssignee("张三").count());
	    System.out.println("***************笔试流程结束***************");
	 
	    System.out.println("\n***************一面流程开始***************");
	    tasks = taskService.createTaskQuery().taskCandidateGroup("技术部").list();
	    for (Task task : tasks) {
	        System.out.println("技术部的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.claim(task.getId(), "李四");
	    }
	 
	    System.out.println("李四的任务数量："+taskService.createTaskQuery().taskAssignee("李四").count());
	    for (Task task : tasks) {
	        System.out.println("李四的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.complete(task.getId());
	    }
	 
	    System.out.println("李四的任务数量："+taskService.createTaskQuery().taskAssignee("李四").count());
	    System.out.println("***************一面流程结束***************");
	 
	    System.out.println("\n***************二面流程开始***************");
	    tasks = taskService.createTaskQuery().taskCandidateGroup("技术部").list();
	    for (Task task : tasks) {
	        System.out.println("技术部的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.claim(task.getId(), "李四");
	    }
	 
	    System.out.println("李四的任务数量："+taskService.createTaskQuery().taskAssignee("李四").count());
	    for (Task task : tasks) {
	        System.out.println("李四的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.complete(task.getId());
	    }
	 
	    System.out.println("李四的任务数量："+taskService.createTaskQuery().taskAssignee("李四").count());
	    System.out.println("***************二面流程结束***************");
	 
	    System.out.println("***************HR面流程开始***************");
	    tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
	    for (Task task : tasks) {
	        System.out.println("技术部的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.claim(task.getId(), "李四");
	    }
	 
	    System.out.println("李四的任务数量："+taskService.createTaskQuery().taskAssignee("李四").count());
	    for (Task task : tasks) {
	        System.out.println("李四的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.complete(task.getId());
	    }
	 
	    System.out.println("李四的任务数量："+taskService.createTaskQuery().taskAssignee("李四").count());
	    System.out.println("***************HR面流程结束***************");
	 
	    System.out.println("\n***************录用流程开始***************");
	    tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
	    for (Task task : tasks) {
	        System.out.println("技术部的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.claim(task.getId(), "李四");
	    }
	 
	    System.out.println("李四的任务数量："+taskService.createTaskQuery().taskAssignee("李四").count());
	    for (Task task : tasks) {
	        System.out.println("李四的任务：name:"+task.getName()+",id:"+task.getId());
	        taskService.complete(task.getId());
	    }
	 
	    System.out.println("李四的任务数量："+taskService.createTaskQuery().taskAssignee("李四").count());
	    System.out.println("***************录用流程结束***************");
	 
	    HistoryService historyService = processEngine.getHistoryService();
	    HistoricProcessInstance historicProcessInstance = historyService
	            .createHistoricProcessInstanceQuery()
	            .processInstanceId(processId).singleResult();
	    System.out.println("\n流程结束时间："+historicProcessInstance.getEndTime());
	}
}
